package com.cat.common.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import com.cat.common.entity.WXAccessToken;
import com.cat.common.entity.WXOAuthCode;
import com.cat.common.entity.WXOAuthToken;
import com.cat.tiger.util.BaseUtils;
import com.cat.tiger.util.HttpClientUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: ninglijun
 * @date: 15/12/28
 * @time: 下午3:52
 * @description:
 */
public class WXAuthUtil {

    private static final Logger logger = LoggerFactory.getLogger(WXAuthUtil.class);
    private static final Pattern WEIXIN_PATTERN = Pattern.compile("MicroMessenger/(\\d+).+");

    /**
     * 判断是否来自微信, 5.0 之后的支持微信支付
     *
     * @param request
     * @return
     */
    public static boolean isWeiXin(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        if (StringUtils.isNotBlank(userAgent)) {
            Matcher m = WEIXIN_PATTERN.matcher(userAgent);
            String version = null;
            if (m.find()) {
                version = m.group(1);
            }
            return (null != version && NumberUtils.toInt(version) >= 5);
        }
        return false;
    }

    public static String createOauthUrlForCode(WXOAuthCode wxoAuthCode) throws UnsupportedEncodingException {
        Map<String, String> params = Maps.newHashMap();
        params.put("appid", wxoAuthCode.getAppId());
        params.put("redirect_uri", wxoAuthCode.getWxOauthDomain() + "?realUri=" + wxoAuthCode.getRedirectUrl());
        params.put("response_type", "code");
        params.put("scope", wxoAuthCode.getScope());
        params.put("state", wxoAuthCode.getState() + "#wechat_redirect");
        String bizString = Signature.mapToSignString(params,false);
        return "https://open.weixin.qq.com/connect/oauth2/authorize?" + bizString;
    }

    public static String getOpenid(WXOAuthToken wxoAuthToken) throws IOException {
        Map<String, Object> rmap = getAccessTokenMap(wxoAuthToken);
        String openId = BaseUtils.getStringValueFromMap(rmap, "openid");
        logger.info("open id is {}", openId);
        return openId;
    }

    public static WXAccessToken getWXAccessToken(WXOAuthToken wxoAuthToken) throws IOException{
        Map<String, Object> rmap = getAccessTokenMap(wxoAuthToken);
        WXAccessToken wxAccessToken = new WXAccessToken();
        wxAccessToken.setAccessToken(BaseUtils.getStringValueFromMap(rmap, "access_token"));
        wxAccessToken.setExpiresIn(BaseUtils.getStringValueFromMap(rmap, "expires_in"));
        wxAccessToken.setOpenid(BaseUtils.getStringValueFromMap(rmap, "openid"));
        wxAccessToken.setRefreshToken(BaseUtils.getStringValueFromMap(rmap, "refresh_token"));
        wxAccessToken.setUnionid(BaseUtils.getStringValueFromMap(rmap, "unionid"));

        return wxAccessToken;
    }

    private static Map<String, Object> getAccessTokenMap(WXOAuthToken wxoAuthToken) throws IOException{
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

            Map<String, String> params = Maps.newHashMap();
            params.put("appid", wxoAuthToken.getAppId());
            params.put("secret", wxoAuthToken.getSecret());
            params.put("code", wxoAuthToken.getCode());
            params.put("grant_type", "authorization_code");
            String bizString = Signature.mapToSignString(params, false);
            String url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + bizString;

            logger.info("requestAttr={}, get openid url = {}", request.getAttribute("wx_oauth_log"), url);
            //取出openid
            String data = HttpClientUtils.doGet(url, null);
            Map<String, Object> rmap = new ObjectMapper().readValue(data.getBytes(), Map.class);

            if (request.getAttribute("wx_oauth_log") != null){
                logger.info("requestAttr => {}, wx return openid data is => {}", request.getAttribute("wx_oauth_log"), data);
                logger.info("requestAttr => {}, parse data is => {}", request.getAttribute("wx_oauth_log"), rmap);
            }else{
                logger.info("wx return openid data is => {}", data);
                logger.info("parse data is => {}", rmap);
            }

            return rmap;
        }catch (Exception e){
            logger.error("微信授权获取AccessToken失败", e);
        }
        return null;
    }
}
